﻿using Microsoft.EntityFrameworkCore;
using MyMes.Dto;
using MyMes.Infrastructure;
using MyMES.Dto;
using MyMES.IServices.Allots;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VOL.Core.BaseProvider;
using VOL.Core.Extensions;
using VOL.Core.Utilities.Response;
using VOL.Entity.DomainModels;
using VOL.Entity.DomainModels.Core;
using VOL.Entity.DomainModels.Repository;

namespace MyMES.Services.Allots
{
    /// <summary>
    /// 调拨服务类，提供调拨相关的业务操作
    /// </summary>
    public class AllotService : IAllotService
    {
        private readonly IBaseRepository<Allot> _allotRepository;
        private readonly IBaseRepository<AllotMaterial> _allotMaterialRepository;
        private readonly IBaseRepository<MaterialProduct> _materialRepository;
        private readonly IBaseRepository<MaterialCatalog> _materialTypeRepository;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="allotRepository">调拨仓储接口</param>
        /// <param name="allotMaterialRepository">调拨物料仓储接口</param>
        /// <param name="materialRepository">物料仓储接口</param>
        /// <param name="materialTypeRepository">物料类型仓储接口</param>
        public AllotService(
            IBaseRepository<Allot> allotRepository,
            IBaseRepository<AllotMaterial> allotMaterialRepository,
            IBaseRepository<MaterialProduct> materialRepository,
            IBaseRepository<MaterialCatalog> materialTypeRepository)
        {
            this._allotRepository = allotRepository;
            this._allotMaterialRepository = allotMaterialRepository;
            this._materialRepository = materialRepository;
            this._materialTypeRepository = materialTypeRepository;
        }

        /// <summary>
        /// 创建调拨记录
        /// </summary>
        /// <param name="entity">调拨实体</param>
        /// <returns>操作结果</returns>
        public async Task<WebResponseContent> CreateAllotAsync(Allot entity)
        {
            WebResponseContent response = new WebResponseContent();
            
            try
            {
                // 验证数据
                if (string.IsNullOrEmpty(entity.AllotCode))
                {
                    return response.Error("调拨编号不能为空");
                }
                
                if (string.IsNullOrEmpty(entity.AllotName))
                {
                    return response.Error("调拨名称不能为空");
                }
                entity.Status = 0; // 假设0是初始状态
                
                // 保存数据
                await _allotRepository.AddAsync(entity);
                
                return response.OK("创建成功");
            }
            catch (Exception ex)
            {
                return response.Error($"创建失败：{ex.Message}");
            }
        }

        /// <summary>
        /// 创建调拨物料
        /// </summary>
        /// <param name="entity">调拨物料实体</param>
        /// <returns>操作结果</returns>
        public async Task<WebResponseContent> CreateAllotMaterialAsync(AllotMaterial entity)
        {
            WebResponseContent response = new WebResponseContent();
            
            try
            {
                // 验证数据
                if (entity.AllotId <= 0)
                {
                    return response.Error("调拨ID无效");
                }
                
                if (entity.MaterialId <= 0)
                {
                    return response.Error("物料ID无效");
                }
                
                // 保存数据
                await _allotMaterialRepository.AddAsync(entity);
                
                return response.OK("创建物料调拨成功");
            }
            catch (Exception ex)
            {
                return response.Error($"创建物料调拨失败：{ex.Message}");
            }
        }

        /// <summary>
        /// 删除调拨记录
        /// </summary>
        /// <param name="ids">调拨ID列表，以逗号分隔的字符串</param>
        /// <returns>操作结果</returns>
        public async Task<WebResponseContent> DelAllotA(string ids)
        {
            WebResponseContent response = new WebResponseContent();
            
            try
            {
                List<int> idList = ids.Split(',').Select(int.Parse).ToList();
                // 调用DelAll方法删除数据
                int result = await _allotRepository.DelAll(a => idList.Contains(a.Id));
                
                if (result > 0)
                {
                    return response.OK($"成功删除{result}条记录");
                }
                else
                {
                    return response.Error("删除失败，请稍后重试");
                }
            }
            catch (Exception ex)
            {
                return response.Error($"删除失败：{ex.Message}");
            }
        }

        /// <summary>
        /// 删除调拨物料记录
        /// </summary>
        /// <param name="ids">调拨物料ID列表，以逗号分隔的字符串</param>
        /// <returns>操作结果</returns>
        public async Task<WebResponseContent> DelAllotMaterialAsync(string ids)
        {
            WebResponseContent response = new WebResponseContent();
            
            try
            {

                List<int> idList = ids.Split(',').Select(int.Parse).ToList();
                
                // 查询这些物料属于哪些调拨单
                var materials = await _allotMaterialRepository.GetAll()
                    .Where(m => idList.Contains(m.Id))
                    .ToListAsync();
                
                var allotIds = materials.Select(m => m.AllotId).Distinct().ToList();

                // 调用DelAll方法删除数据
                int result = await _allotMaterialRepository.DelAll(m => idList.Contains(m.Id));
                
                if (result > 0)
                {
                    return response.OK($"成功删除{result}条物料记录");
                }
                else
                {
                    return response.Error("删除失败，请稍后重试");
                }
            }
            catch (Exception ex)
            {
                return response.Error($"删除物料记录失败：{ex.Message}");
            }
        }

        /// <summary>
        /// 获取调拨记录列表
        /// </summary>
        /// <param name="dto">查询条件</param>
        /// <returns>分页后的调拨记录列表</returns>
        public async Task<PageGridData<Allot>> GetAllotAsync(GetAllotDto dto)
        {
            PageGridData<Allot> pageData = new PageGridData<Allot>();

            try
            {
                // 构建查询条件
                var query = _allotRepository.GetAll();

                // 使用WhereIf方法应用筛选条件
                query = query.WhereIF(!string.IsNullOrEmpty(dto.InformCode), 
                    x => x.AllotCode.Contains(dto.InformCode));
                
                query = query.WhereIF(!string.IsNullOrEmpty(dto.AllotName), 
                    x => x.AllotName.Contains(dto.AllotName));
                
                query = query.WhereIF(!string.IsNullOrEmpty(dto.AllotType), 
                    x => x.AllotType == dto.AllotType);

                // 获取总记录数
                int totalCount = await query.CountAsync();

                // 分页并获取数据
                var data = await query
                    .OrderByDescending(x => x.Id)
                    .Skip((dto.PageIndex - 1) * dto.PageSize)
                    .Take(dto.PageSize)
                    .ToListAsync();

                // 设置返回数据
                pageData.rows = data;
                pageData.total = totalCount;

                return pageData;
            }
            catch (Exception ex)
            {
                // 记录错误并返回空结果
                pageData.rows = new List<Allot>();
                pageData.total = 0;
                return pageData;
            }
        }

        /// <summary>
        /// 根据调拨ID获取物料列表
        /// </summary>
        /// <param name="allotId">调拨ID</param>
        /// <returns>物料列表</returns>
        public async Task<WebResponseContent> GetAllotMaterialListByAllotId(int allotId)
        {
            WebResponseContent response = new WebResponseContent();
            
            try
            {
                // 先获取调拨关联的物料记录
                var allotMaterials = await _allotMaterialRepository.GetAll()
                    .Where(m => m.AllotId == allotId)
                    .ToListAsync();
                
                // 获取物料ID列表
                var materialIds = allotMaterials.Select(am => am.MaterialId).ToList();
                
                // 查询对应的物料信息
                var materials = await _materialRepository.GetAll()
                    .Where(m => materialIds.Contains(m.Id))
                    .ToListAsync();
                
                return response.OK("获取物料列表成功", materials);
            }
            catch (Exception ex)
            {
                return response.Error($"获取物料列表失败：{ex.Message}");
            }
        }

        /// <summary>
        /// 获取物料列表
        /// </summary>
        /// <param name="dto">查询条件</param>
        /// <returns>分页后的物料列表</returns>
        public async Task<PageGridData<MaterialProduct>> GetMaterialAsync(GetMaterialDto dto)
        {
            PageGridData<MaterialProduct> pageData = new PageGridData<MaterialProduct>();

            try
            {
                // 构建查询条件
                var query = _materialRepository.GetAll();

                // 使用WhereIf方法应用筛选条件
                query = query.WhereIF(!string.IsNullOrEmpty(dto.MaterialCode), 
                    x => x.MaterialCode.Contains(dto.MaterialCode));
                
                query = query.WhereIF(!string.IsNullOrEmpty(dto.MaterialName), 
                    x => x.MaterialName.Contains(dto.MaterialName));
                
                query = query.WhereIF(!string.IsNullOrEmpty(dto.FlatsMaterial), 
                    x => x.FlatsMaterial == dto.FlatsMaterial);
                
                query = query.WhereIF(!string.IsNullOrEmpty(dto.RepositoryName), 
                    x => dto.RepositoryName.Contains(dto.RepositoryName));

                // 获取总记录数
                int totalCount = await query.CountAsync();

                // 分页并获取数据
                var data = await query
                    .OrderBy(x => x.MaterialCode)
                    .Skip((dto.PageIndex - 1) * dto.PageSize)
                    .Take(dto.PageSize)
                    .ToListAsync();

                // 设置返回数据
                pageData.rows = data;
                pageData.total = totalCount;

                return pageData;
            }
            catch (Exception ex)
            {
                // 记录错误并返回空结果
                pageData.rows = new List<MaterialProduct>();
                pageData.total = 0;
                return pageData;
            }
        }

        /// <summary>
        /// 获取物料类型列表（树形结构）
        /// </summary>
        /// <returns>物料类型树形列表</returns>
        public async Task<WebResponseContent> GetMaterialTypeList()
        {
            WebResponseContent response = new WebResponseContent();
            
            try
            {
                // 查询所有物料类型
                var allTypes = await _materialTypeRepository.GetAll()
                    .OrderBy(t => t.OrderById)
                    .ToListAsync();
                
                // 转换为树形结构DTO
                List<MaterialTypeTreeDto> treeList = new List<MaterialTypeTreeDto>();
                
                // 首先找出所有顶级分类（ParentId为null或0）
                var rootTypes = allTypes.Where(t => t.ParentId == null || t.ParentId == 0).ToList();
                
                // 为每个顶级分类构建树
                foreach (var rootType in rootTypes)
                {
                    var rootDto = new MaterialTypeTreeDto
                    {
                        Id = rootType.Id,
                        ClassifyName = rootType.ClassifyName,
                        MaterialName = rootType.MaterialName,
                        ParentId = rootType.ParentId,
                        OrderById = rootType.OrderById,
                        Status = rootType.Status,
                        CreateTime = rootType.CreateTime
                    };
                    
                    // 递归添加子分类
                    AddChildTypes(rootDto, allTypes);
                    
                    // 添加到结果列表
                    treeList.Add(rootDto);
                }
                
                return response.OK("获取物料类型树形列表成功", treeList);
            }
            catch (Exception ex)
            {
                return response.Error($"获取物料类型树形列表失败：{ex.Message}");
            }
        }
        
        /// <summary>
        /// 递归添加子分类
        /// </summary>
        /// <param name="parentDto">父分类DTO</param>
        /// <param name="allTypes">所有分类列表</param>
        private void AddChildTypes(MaterialTypeTreeDto parentDto, List<MaterialCatalog> allTypes)
        {
            // 查找当前节点的所有子节点
            var children = allTypes.Where(t => t.ParentId == parentDto.Id).ToList();
            
            foreach (var child in children)
            {
                var childDto = new MaterialTypeTreeDto
                {
                    Id = child.Id,
                    ClassifyName = child.ClassifyName,
                    MaterialName = child.MaterialName,
                    ParentId = child.ParentId,
                    OrderById = child.OrderById,
                    Status = child.Status,
                    CreateTime = child.CreateTime
                };
                
                // 递归添加子分类
                AddChildTypes(childDto, allTypes);
                
                // 添加到父节点的子节点列表
                parentDto.Children.Add(childDto);
            }
        }

        /// <summary>
        /// 更新调拨记录
        /// </summary>
        /// <param name="entity">调拨实体</param>
        /// <returns>操作结果</returns>
        public async Task<WebResponseContent> UpdateAllotAsync(Allot entity)
        {
            WebResponseContent response = new WebResponseContent();

            try
            {
                // 保存更新
                await _allotRepository.UpdateAsync(entity);

                return response.OK("更新成功");
            }
            catch (Exception ex)
            {
                return response.Error($"更新失败：{ex.Message}");
            }
        }

        /// <summary>
        /// 更新调拨物料
        /// </summary>
        /// <param name="entity">调拨物料实体</param>
        /// <returns>操作结果</returns>
        public async Task<WebResponseContent> UpdateMaterialAsync(AllotMaterial entity)
        {
            WebResponseContent response = new WebResponseContent();
            
            try
            {
                // 保存更新
                await _allotMaterialRepository.UpdateAsync(entity);
                
                return response.OK("更新物料记录成功");
            }
            catch (Exception ex)
            {
                return response.Error($"更新物料记录失败：{ex.Message}");
            }
        }
    }
}
